package cn.ithers.blog.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.ithers.blog.dao.ArticleNoAllDao;
import cn.ithers.blog.dao.CommentDao;
import cn.ithers.blog.domain.PageList;
import cn.ithers.blog.dto.CommentDTO;
import cn.ithers.blog.pojo.ArticleNoAll;
import cn.ithers.blog.pojo.Comment;
import cn.ithers.blog.pojo.User;
import cn.ithers.blog.response.ResponseResult;
import cn.ithers.blog.service.ICommentService;
import cn.ithers.blog.service.IUserService;
import cn.ithers.blog.utils.Constants;
import cn.ithers.blog.utils.IdWorker;
import cn.ithers.blog.utils.RedisUtils;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.Date;

/**
 * @Author: zhanghuan
 * @date: 2020/10/11 9:19
 * @description:
 */
@Slf4j
@Service
@Transactional
public class CommentServiceImpl extends BaseService implements ICommentService {

    @Autowired
    private IUserService userService;
    @Autowired
    private IdWorker idWorker;

    @Autowired
    private ArticleNoAllDao articleNoAllDao;

    @Autowired
    private CommentDao commentDao;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private Gson gson;

    /**
     * 发表评论
     *
     * @param commentDTO
     * @return
     */
    @Override
    public ResponseResult postComment(CommentDTO commentDTO) {

        //检查用户是否登录
        User user = userService.checkUser();
        if (user == null) {
            return ResponseResult.ACCOUNT_NOT_LOGIN();
        }
        //检查内容
        String articleId = commentDTO.getArticleId();
        if (StrUtil.isEmpty(articleId)) {
            return ResponseResult.FAILED("文章ID不可为空");
        }

        ArticleNoAll articleNoAll = articleNoAllDao.findOneById(articleId);
        if (articleNoAll == null) {
            return ResponseResult.FAILED("文章不存在");
        }
        String content = commentDTO.getContent();
        if (StrUtil.isEmpty(content)) {
            return ResponseResult.FAILED("评论内容不可为空");
        }
        //补全内容
        Comment comment = new Comment();
        comment.setArticleId(articleId);
        comment.setContent(content);
        comment.setId(idWorker.nextId() + "");
        comment.setCreateTime(new Date());
        comment.setUpdateTime(new Date());
        comment.setUserAvatar(user.getAvatar());
        comment.setUserName(user.getUserName());
        comment.setUserId(user.getId());
        //保存入库
        commentDao.save(comment);
        //清除对应文章的评论缓存
        redisUtils.del(Constants.Comment.KEY_COMMENT_FIRST_PAGE_CACHE + articleId);
        return ResponseResult.SUCCESS("评论成功");
    }

    /**
     * 获取评论列表
     * 评论的排序策略；最基本按时间排列->升序和降序--->先发表在前，或后发表在前
     * <p>
     * 置顶；一直在前面
     * 后发表：前单位时间在前，过来点位时间按照点赞量和单位时间排序
     *
     * @param articleId
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public ResponseResult listComments(String articleId, int page, int pageSize) {
        page = checkPage(page);
        pageSize = checkPageSize(pageSize);
        //如果是第一页，就从缓存中拿
        String cacheJson = (String) redisUtils.get(Constants.Comment.KEY_COMMENT_FIRST_PAGE_CACHE + articleId);
        if (!StrUtil.isEmpty(cacheJson) && page == 1) {
            PageList<Comment> result = gson.fromJson(cacheJson, new TypeToken<PageList<Comment>>() {
            }.getType());
            log.info("comment list form redis");
            return ResponseResult.SUCCESS("获取评论列表成功").setData(result);
        }

        //如果没有就一致往下走
        ArticleNoAll articleNoAll = articleNoAllDao.findOneById(articleId);
        if (articleNoAll == null) {
            return ResponseResult.FAILED("文章不存在");
        }
        Sort sort = Sort.by(Sort.Direction.DESC, "state", "createTime");
        Pageable pageable = PageRequest.of(page - 1, pageSize, sort);
        Page<Comment> all = commentDao.findAllByArticleId(articleId, pageable);
        //把结果转成pageList
        PageList<Comment> result = new PageList<>();
        result.parsePage(all);
        //保存一份到redis
        if (page == 1) {
            //保存1小时
            redisUtils.set(Constants.Comment.KEY_COMMENT_FIRST_PAGE_CACHE + articleId, gson.toJson(result),
                    Constants.TimeValueInSecond.HOUR);
        }
        return ResponseResult.SUCCESS("获取评论列表成功").setData(result);
    }

    /**
     * 删除评论
     *
     * @param commentId
     * @return
     */
    @Override
    public ResponseResult deleteComment(String commentId) {
        User user = userService.checkUser();
        if (user == null) {
            return ResponseResult.ACCOUNT_NOT_LOGIN();
        }
        //登陆了要判断角色
        Comment commentFromDb = commentDao.findOneById(commentId);
        if (commentFromDb == null) {
            return ResponseResult.FAILED("评论不存在");
        }
        if (user.getId().equals(commentFromDb.getUserId()) || Constants.User.ROLE_ADMIN.equals(user.getRoles())) {
            //用户id一致 或着是管理员 可以删除
            commentDao.deleteById(commentId);
            return ResponseResult.SUCCESS("评论删除成功");
        } else {
            return ResponseResult.FAILED("你不能删除别人评论");
        }
    }

    /**
     * 获取评论列表
     * 管理员使用
     *
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public ResponseResult listComments(int page, int pageSize) {
        page = checkPage(page);
        pageSize = checkPageSize(pageSize);
        Sort sort = Sort.by(Sort.Direction.DESC, "createTime");
        Pageable pageable = PageRequest.of(page - 1, pageSize, sort);
        Page<Comment> all = commentDao.findAll(pageable);

        return ResponseResult.SUCCESS("获取评论列表成功").setData(all);
    }

    /**
     * 评论置顶
     *
     * @param commentId
     * @return
     */
    @Override
    public ResponseResult topComment(String commentId) {
        Comment commentFromDb = commentDao.findOneById(commentId);
        if (commentFromDb == null) {
            return ResponseResult.FAILED("评论不存在");
        }
        String state = commentFromDb.getState();
        if (Constants.Comment.STATE_PUBLISH.equals(state)) {
            commentFromDb.setState(Constants.Comment.STATE_TOP);
            return ResponseResult.SUCCESS("置顶成功");

        } else if (Constants.Comment.STATE_TOP.equals(state)) {
            commentFromDb.setState(Constants.Comment.STATE_PUBLISH);
            return ResponseResult.SUCCESS("取消置顶");
        } else {
            return ResponseResult.FAILED("评论状态非法");
        }

    }
}
